#![allow(dead_code)]

struct SliceLrn {}

impl SliceLrn {
    pub fn hello() {
        println!("Slice learning!");
    }
}

#[cfg(test)]
mod tests {
    use std::cmp::Reverse;

    #[test]
    #[allow(unused)]
    #[allow(clippy::useless_vec)]
    /// NOTE: 切片是一个内存块的视图，表示为一个指针和一个长度。
    fn test_slice() {
        let vec = vec![1, 2, 3];
        let int_slice = &vec[..]; // 切片
        let str_slice1 = &["one", "two", "three"];
        let str_slice2 = &vec![1, 2, 3][0..2]; // 切片
        let str_slice3 = &[1, 2, 3][0..2]; // 切片必须是指针类型

        println!("str_slice2: {:?}", str_slice2);
    }

    #[test]
    /// NOTE: 切片存储是Sized类型的两倍。
    fn test_size() {
        let pointer_size = std::mem::size_of::<&usize>();
        assert_eq!(2 * pointer_size, std::mem::size_of::<&[usize]>());
        assert_eq!(2 * pointer_size, std::mem::size_of::<&[u8]>());
        assert_eq!(2 * pointer_size, std::mem::size_of::<*const [usize]>());
        assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[usize]>>());
        assert_eq!(
            2 * pointer_size,
            std::mem::size_of::<std::rc::Rc<[usize]>>()
        );
    }

    #[test]
    #[allow(clippy::useless_vec)]
    fn test_contains() {
        let v = vec![1, 2, 3, 4, 5];
        assert!(v.contains(&3));
    }

    #[test]
    fn test_iter_slice() {
        // NOTE: 相等iter_mut() == &mut
        // 迭代器是引用
        let mut vec = vec![1, 2, 3];
        for v in vec.iter_mut() {
            *v += 1;
        }
        assert_eq!(vec, [2, 3, 4]);
        for x in &mut vec {
            *x += 1;
        }
        assert_eq!(vec, [3, 4, 5]);

        let arr_slice = &mut [1, 2, 3];
        // 切片可以iter
        // 相同: for s in &mut *arr_slice {
        for s in arr_slice.iter_mut() {
            *s += 1;
        }
        // arr_slice 是可变切片
        assert_eq!(*arr_slice, [2, 3, 4]);
    }

    #[test]
    fn test_as_ptr() {
        // 可变数组
        let mut x = [1, 2, 4];
        let x_ptr = x.as_mut_ptr();

        // 可变切片
        let y = &mut [3, 4, 6];
        let y_ptr = y.as_mut_ptr();

        unsafe {
            for i in 0..x.len() {
                *x_ptr.add(i) += 2;
            }
            for u in 0..y.len() {
                *y_ptr.add(u) += 3;
            }
        }
        assert_eq!(x, [3, 4, 6]);
        assert_eq!(y, &[6, 7, 9]);
    }

    #[test]
    /// Chunks是一个迭代器, 返回切片的chunk_size元素的迭代器。
    fn test_chunks() {
        let array = [1, 2, 3, 4, 5, 6, 7, 8];
        let nested_array: Vec<Vec<i32>> = array.chunks(3).map(|c| c.to_vec()).collect();
        assert_eq!(nested_array, vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8]]);

        let flatten_array: Vec<i32> = nested_array.into_iter().flatten().collect();
        assert_eq!(flatten_array, vec![1, 2, 3, 4, 5, 6, 7, 8]);
    }

    #[test]
    /// 从切片的开头开始，一次返回对切片的chunk_size元素的迭代器。
    fn test_chunks_mut() {
        // 切片
        let v = &mut [0; 5];
        let mut count = 1;

        for chunk in v.chunks_mut(2) {
            for elem in chunk.iter_mut() {
                *elem = count;
            }
            count += 1;
        }
        assert_eq!(v, &[1, 1, 2, 2, 3]);
    }

    #[test]
    #[allow(clippy::useless_vec)]
    #[allow(unused_variables)]
    ///
    fn test_flatten() {
        // array
        let v = [1, 2, 3, 4, 5, 6];
        let x = [[1, 2, 3], [4, 5, 6]];

        // vec!
        let a = vec![1, 2, 3, 4, 5, 6];
        let b = vec![vec![1, 2, 3], vec![4, 5, 6]];
        let c = vec![&[1, 2, 3], &[4, 5, 6]];

        // chunks得到的是切片
        // - 直接collect，得到chunks: [&[1, 2, 3], &[4, 5, 6]];
        // 这个办法不好，这个是一个vec，里面的元素是切片&[i32]
        let chunks_arr: Vec<&[i32]> = v.chunks(3).collect();

        // - 将切片转换为Vec，vec嵌套是Vec<Vec<i32>>
        let chunks_vec: Vec<Vec<i32>> = v.chunks(3).map(|c| c.to_vec()).collect();
        assert_eq!(chunks_arr, vec![&[1, 2, 3], &[4, 5, 6]]);
        assert_eq!(chunks_vec, vec![vec![1, 2, 3], vec![4, 5, 6]]);

        // - flatten
        // - 把vec嵌套vec展平
        let flatten_vec: Vec<i32> = chunks_vec.into_iter().flatten().collect();
        // - 把vec嵌套array展平, flatten()后，元素为&i32, 可以用copied()转换为i32
        let flatten_arr = chunks_arr
            .into_iter()
            .flatten()
            .copied()
            .collect::<Vec<i32>>();
        assert_eq!(flatten_arr, vec![1, 2, 3, 4, 5, 6]);
        assert_eq!(flatten_vec, vec![1, 2, 3, 4, 5, 6]);
    }

    #[test]
    fn test_rotate() {
        let mut v = [1, 2, 3, 4, 5];
        v.rotate_left(2);
        assert_eq!(v, [3, 4, 5, 1, 2]);
        v.rotate_right(2);
        assert_eq!(v, [1, 2, 3, 4, 5]);
    }

    #[test]
    #[allow(clippy::useless_vec)]
    fn test_first_last() {
        let v = vec![1, 2, 3, 4, 5];
        let x = v.first();
        let y = *v.last().unwrap();
        assert_eq!(x, Some(&1));
        assert_eq!(y, 5);
    }

    #[test]
    #[allow(clippy::useless_vec)]
    fn test_get() {
        let v = vec![1, 2, 3, 4, 5];
        let x = v.get(1);
        assert_eq!(Some(&2), x);
        let y = *v.get(2).unwrap();
        assert_eq!(3, y);
    }

    #[test]
    #[allow(clippy::useless_vec)]
    fn test_split_at() {
        let v = vec![1, 2, 3, 4, 5];
        let (left, right) = v.split_at(2);
        assert_eq!(left, [1, 2]);
        assert_eq!(right, [3, 4, 5]);
    }

    #[test]
    #[allow(unused)]
    fn test_split_at_mut() {
        let mut v = vec![1, 2, 3, 4, 5, 7];
        let (left, right) = v.split_at_mut(3);
        left[1] = 10;
        assert_eq!(left, [1, 10, 3]);
        assert_eq!(v, [1, 10, 3, 4, 5, 7]);
    }

    #[test]
    fn test_split_mut() {
        let mut v = [10, 40, 30, 20, 60, 50];

        for group in v.split_mut(|num| *num % 3 == 0) {
            group[0] = 1;
        }
        assert_eq!(v, [1, 40, 30, 1, 60, 1]);
    }

    #[test]
    /// 在子切片上返回一个迭代器，该子切片由与 pred 匹配的元素分隔.
    fn test_splitn() {
        let mut v = [10, 20, 30, 40, 50, 60, 70, 80, 90];
        for group in v.splitn_mut(3, |num| *num % 3 == 0) {
            group[0] = 1;
        }
        assert_eq!(v, [1, 20, 30, 1, 50, 60, 1, 80, 90]);
    }

    #[test]
    fn test_windows() {
        let string = ['r', 'u', 's', 't'];
        let mut iter = string.windows(3);

        assert_eq!(iter.next().unwrap(), &['r', 'u', 's']);
        assert_eq!(iter.next().unwrap(), &['u', 's', 't']);
        assert!(iter.next().is_none());
    }

    #[test]
    fn sort_by_key_test() {
        let mut v = vec!["klmno", "def", "bc", "ghij", "a", "pqrstu", "vwxyz"];
        // NOTE: 我理解，sort_by_key是按照key排序，key是一个元组，元组的第一个元素是bool类型，第二个元素是字符串的反转。
        // Reverse 是个辅助结构，空结构
        v.sort_by_key(|&s| (s.len() > 3, Reverse(s)));
        println!("{:?}", v);
    }
}
